package com.example.ourradio;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.ispeech.SpeechSynthesis;
import org.ispeech.error.BusyException;
import org.ispeech.error.InvalidApiKeyException;
import org.ispeech.error.NoNetworkException;

import android.app.Activity;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;

public class DownloadTTSTask extends AsyncTask<String, Void, byte[]> {
	private static final String TAG = "TTS";
	
	private Activity mActivity;
	private AudioFragment mAudioFrag;
	private SpeechSynthesis mSynthesis = null;
	
	public DownloadTTSTask(Activity activity, AudioFragment audioFrag) {
		mActivity = activity;
		mAudioFrag = audioFrag;
		prepareTTSEngine(activity);
	}
	
    @Override
    protected byte[] doInBackground(String ... urls) {
        return downloadByteArray(urls[0]);
    }

    @Override
    protected void onPostExecute(byte[] bytes) {
    	mAudioFrag.playTTSAudio(bytes);
    }
    	
	private static ArrayList<String> unicodeChunks(
		String str, 
		int numOfUcPerChunk
	) {
		int numOfC = str.length();
		int restNumOfUC = str.codePointCount(0, numOfC);
		ArrayList<String> re = new ArrayList<String>(); 
		int offset = 0;
				
		while (offset < numOfC && restNumOfUC >= numOfUcPerChunk) {
			int nextOffset = 
				str.offsetByCodePoints(offset, numOfUcPerChunk);
			re.add(str.substring(offset, nextOffset));
			offset = nextOffset;
			restNumOfUC = restNumOfUC - numOfUcPerChunk;
		}
				
		if (offset < numOfC) {
			re.add(str.substring(offset, numOfC));
		}
				
		return re;
	}	
	
	private void downloadByteArray(
		String text, 
		ByteArrayOutputStream outputStream
	) {
		if (null == mSynthesis) {
			return;
		}
		
		try {
			byte[] bytes = mSynthesis.downloadByteArray(text);
			if (null != bytes) {
				outputStream.write(bytes);	
			}			
		} catch (BusyException e) {
			Log.e(TAG, "SDK is busy");
			e.printStackTrace();
			Toast.makeText(
				mActivity.getApplicationContext(), 
				"ERROR: SDK is busy", 
				Toast.LENGTH_LONG
			).show();
		} catch (NoNetworkException e) {
			Log.e(TAG, "Network is not available\n" + e.getStackTrace());
			Toast.makeText(
				mActivity.getApplicationContext(), 
				"ERROR: Network is not available", 
				Toast.LENGTH_LONG
			).show();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
	
	private byte[] downloadByteArray(String text) {
		ArrayList<String> texts = unicodeChunks(text, 50);
		int chunkIdx = 0;
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
		
		while (chunkIdx < texts.size()) {
			downloadByteArray(texts.get(chunkIdx), outputStream);
			chunkIdx++;
		}
		
		return outputStream.toByteArray();
	}	
	
	private void prepareTTSEngine(Activity activity) {
		try {
			mSynthesis = SpeechSynthesis.getInstance(activity);
			mSynthesis.setStreamType(AudioManager.STREAM_MUSIC);
			mSynthesis.setVoiceType("chchinesefemale");
		} catch (InvalidApiKeyException e) {
			Log.e(TAG, "Invalid API key\n" + e.getStackTrace());
			Toast.makeText(
					activity.getApplicationContext(), 
					"ERROR: Invalid API key", 
					Toast.LENGTH_LONG
			).show();
		}
	}
}
